package com.home766.controller.util;

import com.home766.util.DateTime;
import com.home766.util.StringUtil;
import com.home766.util.XORUtil;
import net.biz.controller.admin.BaseController;
import net.biz.entity.Order;
import net.biz.entity.Order.PaymentStatus;
import net.biz.service.OrderService;
import net.biz.util.ParamsUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;

@Controller
@RequestMapping("/pos")
public class PosController extends BaseController {
	
	@Resource(name = "orderServiceImpl")
	private OrderService orderServiceImpl;
	
	private String DEFAULTC_MAC="1234567890";
	/**
	 * 交易类型（查询返回）
	 */
	private static String SEARCHBACKC_TRANSACTION_TYPE="0110";
	/**
	 * 交易类型（确认返回）
	 */
	private static String CONFIRMC_TRANSACTION_TYPE="0210";
	/**
	 * 银行类型（公用）
	 */
	private static String C_BANK_TYPE="206";
	/**
	 * 银行代码（公用）
	 */
	private static String C_BANK_CODE="allinpay";
	/**
	 * 查询请求类型
	 */
	private static String REQUESTTYPE="0100";
	
	/**
	 * 确认成功状态
	 */
	private static String CONFIRMC_STATUS="200";
	
	/**
	 * 查询确认订单
	 * POS机访问
	 * @param source
	 * @param requestType
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/searchConfirmOrder")
	public String searchConfirmOrder(HttpServletRequest request, HttpServletResponse response){
		String dateString=DateTime.dateTimeToString(new Date());
		System.out.println("__>____>____>_>_--.-.--_.._>进入post机查询确认方法>>>___"+dateString+"_____--..___>");
		String resultStr=showParams(request);
		if(StringUtil.isNullOrSpace(resultStr)){
			try {
				//报文为空响应状态 403
				response.sendError(HttpServletResponse.SC_FORBIDDEN, "Bad or missing token!");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(resultStr.length()<50){
			return getDefaultXML();
		}
		Document document=getDocument(resultStr);//转换成xml对象
		//查询
		String originalData= getText("body","originalData", document);//获取originalData标签中的base64字符串
		originalData=originalData.replaceAll(" ", "+");
		String mac= getText("body","mac", document);//获取mac编码
		String C_TRANSACTION_TYPE="";//定义参数接受请求类型编码
		String N_TRANSACTION_AMOUNT="";
		String C_BANK_REFERENCE_NO="";
		String C_MERCHANT_CODE="";
		String C_MERCHANT_NAME="";
		String C_SERIAL_NO="";
		String C_POS_NO="";
		String T_TRANSACTION_DATE="";
		String C_CARD_NO="";
		String C_BANK_SERIAL_NO="";
		//验证  mac
		try {
			String rootElement="ROOT";
			String tempMac=XORUtil.getMac(originalData);//异或报文中originalData标签中的base64字符串得到mac编码
			Document doc=null;
			//转码base64字符串
			byte[] b= decode(originalData);
			String tempStr=new String(b);
			System.out.println("<<<<<<<<<<<<<<<<<<<<解码开始：");
			System.out.println();
			System.out.println();
			System.out.println(tempStr);
			System.out.println();
			System.out.println();
			System.out.println("<<<<<<<<<<<<<<<<<<<<解码结束：");
			doc=getDocument(tempStr);//获取转码后的 xml  document对象
			//判断doc 是否为空
			
			C_TRANSACTION_TYPE=getText(rootElement,"C_TRANSACTION_TYPE", doc);//获取请求类型
			N_TRANSACTION_AMOUNT=getText(rootElement,"N_TRANSACTION_AMOUNT", doc);
			C_BANK_REFERENCE_NO=getText(rootElement,"C_BANK_REFERENCE_NO", doc);
			C_MERCHANT_CODE=getText(rootElement,"C_MERCHANT_CODE", doc);
			C_MERCHANT_NAME=getText(rootElement,"C_MERCHANT_NAME", doc);
			C_SERIAL_NO=getText(rootElement,"C_SERIAL_NO", doc);//订单号
			C_POS_NO=getText(rootElement,"C_POS_NO", doc);//pos终端号
			T_TRANSACTION_DATE=getText(rootElement,"T_TRANSACTION_DATE", doc);//交易时间
			C_CARD_NO=getText(rootElement,"C_CARD_NO", doc);//缴费卡号
			C_BANK_SERIAL_NO=getText(rootElement,"C_BANK_SERIAL_NO", doc);//银行流水号
			
			if(!tempMac.equalsIgnoreCase(mac)){//对比mac编码
				System.out.println("mac编码验证不通过");
				return getXml(DEFAULTC_MAC, null, null, C_BANK_SERIAL_NO, C_BANK_SERIAL_NO, C_SERIAL_NO, C_BANK_REFERENCE_NO, "999", C_MERCHANT_CODE, C_MERCHANT_NAME, C_POS_NO, N_TRANSACTION_AMOUNT, C_CARD_NO, C_BANK_SERIAL_NO, T_TRANSACTION_DATE, C_TRANSACTION_TYPE);
			}
			//判断转码后的字符串是否为空串货null
			if(!StringUtil.isNullOrSpace(tempStr)){
				String C_STATUS="120";//支付类型，默认已支付
			
//				String C_SERIAL_NO=getText(rootElement,"C_SERIAL_NO", doc);//获取订单号
				Order order=orderServiceImpl.findBySn(C_SERIAL_NO);//根据订单号查询订单
				System.out.println("订单号"+C_SERIAL_NO+"默认状态："+C_STATUS);
				if(order==null){//如果订单为空则返回相应报文
					C_STATUS="110";
				}else{
					//判断订单类型，判断是否支付完毕
					if(order.getOrderType()== ParamsUtil.CART_TYPE_NORMAL){
						if(order.getPaymentStatus()== PaymentStatus.paid){
							C_STATUS="120";
						}else{
							C_STATUS="100";
						}
					}else{
						if(order.getSchemePaymentStatus()== ParamsUtil.SCHEME_PAYMENT_STATUS_PAID){
							C_STATUS="120";
						}else{
							C_STATUS="100";
						}
					}
				}
				if(C_TRANSACTION_TYPE.equals(REQUESTTYPE)){
					return searchOrder(rootElement,doc, C_STATUS, order);
				}else{
					return confirmOrder(rootElement,doc, CONFIRMC_STATUS, order);
				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return getXml(DEFAULTC_MAC, null, null, C_BANK_SERIAL_NO, C_BANK_SERIAL_NO, C_SERIAL_NO, C_BANK_REFERENCE_NO, "999", C_MERCHANT_CODE, C_MERCHANT_NAME, C_POS_NO, N_TRANSACTION_AMOUNT, C_CARD_NO, C_BANK_SERIAL_NO, T_TRANSACTION_DATE, C_TRANSACTION_TYPE);
		}
		 return getXml(DEFAULTC_MAC, null, null, C_BANK_SERIAL_NO, C_BANK_SERIAL_NO, C_SERIAL_NO, C_BANK_REFERENCE_NO, "999", C_MERCHANT_CODE, C_MERCHANT_NAME, C_POS_NO, N_TRANSACTION_AMOUNT, C_CARD_NO, C_BANK_SERIAL_NO, T_TRANSACTION_DATE, C_TRANSACTION_TYPE);
	}
	
	/**
	 * 查询订单
	 * @param doc
	 * @param C_STATUS
	 * @param order
	 * @return
	 */
	private String searchOrder(String rootElement, Document doc, String C_STATUS, Order order){
		String N_TRANSACTION_AMOUNT="";
		String phone=null;
		if(order!=null){
			phone=order.getPhone();
			BigDecimal shouldPay=order.getAmountPayable();
			BigDecimal tempMoney= shouldPay.multiply(new BigDecimal("100"));
			N_TRANSACTION_AMOUNT= String.valueOf(tempMoney).split("\\.")[0];
		}
		String C_MERCHANT_CODE=getText(rootElement,"C_MERCHANT_CODE", doc);
		String C_MERCHANT_NAME=getText(rootElement,"C_MERCHANT_NAME", doc);
		String C_POS_NO=getText(rootElement,"C_POS_NO",doc);
		String C_NAME=getText(rootElement,"C_NAME",doc);
		String C_CARD_NO=getText(rootElement,"C_CARD_NO",doc);
		String C_BANK_SERIAL_NO=getText(rootElement,"C_BANK_SERIAL_NO",doc);
		String C_SERIAL_NO=getText(rootElement,"C_SERIAL_NO",doc);
		String C_BANK_REFERENCE_NO=getText(rootElement,"C_SERIAL_NO",doc);
		String T_TRANSACTION_DATE=getText(rootElement,"T_TRANSACTION_DATE", doc);
		if(StringUtil.isNullOrSpace(T_TRANSACTION_DATE)){
			T_TRANSACTION_DATE=DateTime.timeToString(new Date());
		}
		return getXml(DEFAULTC_MAC, phone, C_NAME, C_BANK_TYPE, C_BANK_CODE, C_SERIAL_NO, C_BANK_REFERENCE_NO, C_STATUS, C_MERCHANT_CODE, C_MERCHANT_NAME, C_POS_NO, N_TRANSACTION_AMOUNT, C_CARD_NO, C_BANK_SERIAL_NO, T_TRANSACTION_DATE, SEARCHBACKC_TRANSACTION_TYPE);
	}
	
	/**
	 * 确认订单
	 * @param doc
	 * @param C_STATUS
	 * @param order
	 * @return
	 */
	private String confirmOrder(String rootElement, Document doc, String C_STATUS, Order order){
		String N_TRANSACTION_AMOUNT=getText(rootElement,"N_TRANSACTION_AMOUNT", doc);
		String C_BANK_REFERENCE_NO=getText(rootElement,"C_BANK_REFERENCE_NO", doc);
		String C_MERCHANT_CODE=getText(rootElement,"C_MERCHANT_CODE", doc);
		String C_MERCHANT_NAME=getText(rootElement,"C_MERCHANT_NAME", doc);
		String C_SERIAL_NO=getText(rootElement,"C_SERIAL_NO", doc);//订单号
		String C_POS_NO=getText(rootElement,"C_POS_NO", doc);//pos终端号
		String T_TRANSACTION_DATE=getText(rootElement,"T_TRANSACTION_DATE", doc);//交易时间
		String C_CARD_NO=getText(rootElement,"C_CARD_NO", doc);//缴费卡号
		String C_BANK_SERIAL_NO=getText(rootElement,"C_BANK_SERIAL_NO", doc);//银行流水号
		@SuppressWarnings("unused")
        String C_PAYTYPE=getText(rootElement,"C_PAYTYPE", doc);//01-	现金
												  //02-	通联银行卡
												 //03-	通联pos储值卡
												//04-	支付宝支付
											   //05-	提货券
											  //06-	积分
											 //07-	通联pos-和信通
		if(order!=null){
			BigDecimal price=new BigDecimal(N_TRANSACTION_AMOUNT);
			price=price.divide(new BigDecimal("100"),2, BigDecimal.ROUND_HALF_UP);
			try {
				String orderDatetime=DateTime.timeToString(order.getCreateDate());
				int i=orderServiceImpl.updatePaymentStatus(C_SERIAL_NO, price,C_SERIAL_NO,orderDatetime,T_TRANSACTION_DATE,getCurrent(),C_BANK_SERIAL_NO,C_CARD_NO);
				if(i==0){
					C_STATUS="999";
				}
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				C_STATUS="999";
			}
		}else{
			C_STATUS="110";
		}
		Order orderTemp=orderServiceImpl.findBySn(C_SERIAL_NO);//根据订单号查询订单
		N_TRANSACTION_AMOUNT = orderTemp.getPercentPrice().toString();//把剩余应付金额传过去
		return getXml(DEFAULTC_MAC, null,null, C_BANK_TYPE, C_BANK_CODE, C_SERIAL_NO, C_BANK_REFERENCE_NO, C_STATUS, C_MERCHANT_CODE, C_MERCHANT_NAME, C_POS_NO, N_TRANSACTION_AMOUNT, C_CARD_NO, C_BANK_SERIAL_NO, T_TRANSACTION_DATE, CONFIRMC_TRANSACTION_TYPE);
	}
	
	
	/**
	 * 拼装xml报文
	 * @param C_MAC  固定值
	 * @param C_TEL_NO
	 * @param C_NAME
	 * @param C_BANK_TYPE
	 * @param C_BANK_CODE
	 * @param C_SERIAL_NO
	 * @param C_BANK_REFERENCE_NO
	 * @param C_STATUS
	 * @param C_MERCHANT_CODE
	 * @param C_MERCHANT_NAME
	 * @param C_POS_NO
	 * @param N_TRANSACTION_AMOUNT
	 * @param C_CARD_NO
	 * @param C_BANK_SERIAL_NO
	 * @param T_TRANSACTION_DATE
	 * @param C_TRANSACTION_TYPE
	 * @return
	 */
	public String getXml(String C_MAC, String C_TEL_NO, String C_NAME, String C_BANK_TYPE, String C_BANK_CODE, String C_SERIAL_NO, String C_BANK_REFERENCE_NO, String C_STATUS, String C_MERCHANT_CODE, String C_MERCHANT_NAME, String C_POS_NO, String N_TRANSACTION_AMOUNT, String C_CARD_NO, String C_BANK_SERIAL_NO, String T_TRANSACTION_DATE, String C_TRANSACTION_TYPE){
		if(StringUtil.isNullOrSpace(N_TRANSACTION_AMOUNT)){
			N_TRANSACTION_AMOUNT="0";
		}
		String returnXml = "<?xml version=\"1.0\" encoding=\"GBK\" ?>";
		returnXml += "<ROOT>";
		String defaultRoot="<C_TRANSACTION_TYPE>"+C_TRANSACTION_TYPE+"</C_TRANSACTION_TYPE>";
				defaultRoot+="<C_BANK_TYPE>"+C_BANK_TYPE+"</C_BANK_TYPE>";
				defaultRoot+="<C_BANK_CODE>"+C_BANK_CODE+"</C_BANK_CODE>";
				defaultRoot+="<C_MERCHANT_CODE>"+C_MERCHANT_CODE+"</C_MERCHANT_CODE>";
				defaultRoot+="<C_MERCHANT_NAME>"+C_MERCHANT_NAME+"</C_MERCHANT_NAME>";
				defaultRoot+="<C_POS_NO>"+C_POS_NO+"</C_POS_NO>";
				defaultRoot+="<C_SERIAL_NO>"+C_SERIAL_NO+"</C_SERIAL_NO>";
				defaultRoot+="<N_TRANSACTION_AMOUNT>"+N_TRANSACTION_AMOUNT+"</N_TRANSACTION_AMOUNT>";
				defaultRoot+="<C_CARD_NO>"+C_CARD_NO+"</C_CARD_NO>";
				defaultRoot+="<C_BANK_SERIAL_NO>"+C_BANK_SERIAL_NO+"</C_BANK_SERIAL_NO>";
				defaultRoot+="<C_BANK_REFERENCE_NO>"+C_BANK_REFERENCE_NO+"</C_BANK_REFERENCE_NO>";
				defaultRoot+="<C_STATUS>"+C_STATUS+"</C_STATUS>";
		
		if(C_NAME!=null){
			defaultRoot+="<C_NAME>"+C_NAME+"</C_NAME>";
		}
		if(C_TEL_NO!=null){
			defaultRoot+="<C_TEL_NO>"+C_TEL_NO+"</C_TEL_NO>";
		}
		defaultRoot+="<T_TRANSACTION_DATE>"+T_TRANSACTION_DATE+"</T_TRANSACTION_DATE>";
		defaultRoot+="<C_MAC>"+C_MAC+"</C_MAC>";
		returnXml += defaultRoot;
		returnXml += "</ROOT>";
		String xorStr="";
		String resultMac="";
		try {
			xorStr=encode(returnXml.getBytes("gbk"));
			resultMac=XORUtil.getMac(xorStr);
		} catch (Exception e) {
			e.printStackTrace();
		}
		String rootXml = "<?xml version=\"1.0\" encoding=\"GBK\" ?>";
		rootXml+="<request>";
		rootXml+="<header>";
		rootXml+="<sender>ccb_pos</sender>";
		rootXml+="<time>"+T_TRANSACTION_DATE+"</time>";
		rootXml+="</header>";
		rootXml+="<body>";
		rootXml+="<originalData>";
		rootXml+=xorStr;
		rootXml+="</originalData>";
		rootXml+="<mac>"+resultMac+"</mac>";
		rootXml+="</body>";
		rootXml+="</request>";
		
		System.out.println("发送到通联的报文:  交易类型:"+C_TRANSACTION_TYPE+" 回执类型："+C_BANK_TYPE +"回执状态："+C_STATUS);
		System.out.println("*****************************");
		System.out.println();
		System.out.println();
        System.out.println(rootXml);
    	System.out.println();
    	System.out.println();
        System.out.println("*****************************");
		return rootXml;
	}
	
	/**
	 * 将xml转换成document对象
	 * @param xml
	 * @return
	 */
	private Document getDocument(String xml){
		Document document=null;
		try {
			document = DocumentHelper.parseText(xml);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return document;
		}  
		return document;
	}
	/**
	 * 获取某个节点的文本内容
	 * @param element
	 * @param document
	 * @return
	 */
	private String getText(String rootEle, String element, Document document){
		Element root = document.getRootElement();  
		Iterator iter = root.elementIterator(rootEle); // 获取根节点下的子节点body
		if(!rootEle.equals("ROOT")){
			while(iter.hasNext()){
				Element recordEle = (Element) iter.next();  
				String child = recordEle.elementTextTrim(element); // 拿到body节点下的子
				return child;
			}
		}else{
			return root.elementText(element);
		}
		return "";
		
	}
	
	/**
	 * 编码
	 * 
	 * @param bstr
	 * @return String
	 */
	public static String encode(byte[] bstr) {
		return new sun.misc.BASE64Encoder().encode(bstr);
	}

	/**
	 * 解码
	 * 
	 * @param str
	 * @return string
	 */
	public static byte[] decode(String str) {
		byte[] bt = null;
		try {
			sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
			bt = decoder.decodeBuffer(str);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return bt;
	}
	/**
	 * 获取报文内容
	 * @param request
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private String showParams(HttpServletRequest request) {
        String resultStr="";
        Enumeration paramNames = request.getParameterNames();
        String resultStr0="";
        while (paramNames.hasMoreElements()) {  
            String paramName = (String) paramNames.nextElement();
            resultStr0=paramName;
            String[] paramValues = request.getParameterValues(paramName);
            if (paramValues.length == 1) {  
                String paramValue = paramValues[0];
                resultStr=paramValue;
                break;
            }  
        }  
        if(resultStr0.indexOf("=")==-1){
        	resultStr0+="=";
        }
        resultStr0=resultStr0.trim();
        System.out.println("*****************************");
        
        System.out.println(resultStr0+resultStr);
        
        System.out.println("*****************************");
        return resultStr0+resultStr;
    } 
	
	private String getDefaultXML(){
		String returnXml = "<?xml version=\"1.0\" encoding=\"GBK\" ?>";
		returnXml += "<ROOT>";
		String defaultRoot="<C_TRANSACTION_TYPE>"+SEARCHBACKC_TRANSACTION_TYPE+"</C_TRANSACTION_TYPE>";
				defaultRoot+="<C_BANK_TYPE>"+C_BANK_TYPE+"</C_BANK_TYPE>";
				defaultRoot+="<C_BANK_CODE>"+C_BANK_CODE+"</C_BANK_CODE>";
				defaultRoot+="<C_MERCHANT_CODE>109050281602005</C_MERCHANT_CODE>";
				defaultRoot+="<C_MERCHANT_NAME>成都七六六智能家居有限公司</C_MERCHANT_NAME>";
				defaultRoot+="<C_POS_NO>0</C_POS_NO>";
				defaultRoot+="<C_SERIAL_NO>0</C_SERIAL_NO>";
				defaultRoot+="<N_TRANSACTION_AMOUNT>0</N_TRANSACTION_AMOUNT>";
				defaultRoot+="<C_CARD_NO>0</C_CARD_NO>";
				defaultRoot+="<C_BANK_SERIAL_NO>0</C_BANK_SERIAL_NO>";
				defaultRoot+="<C_BANK_REFERENCE_NO>0</C_BANK_REFERENCE_NO>";
				defaultRoot+="<C_STATUS>999</C_STATUS>";
		
//		String sdfsdf="<?xml version=\"1.0\" encoding=\"GBK\" ?><request><header><sender>ccb_pos</sender><serviceName>pos_service</serviceName><time>20160229173257</time></header><body><originalData>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iR0JLIiA/PjxST09UPjxDX1RSQU5TQUNUSU9OX1RZUEU+MDEwMDwvQ19UUkFOU0FDVElPTl9UWVBFPjxDX0JBTktfVFlQRT4yMDY8L0NfQkFOS19UWVBFPjxDX0JBTktfQ09ERT5hbGxpbnBheTwvQ19CQU5LX0NPREU+PENfTUVSQ0hBTlRfQ09ERT44MjE1MTAxNTgxMjAxOTg8L0NfTUVSQ0hBTlRfQ09ERT48Q19NRVJDSEFOVF9OQU1FPlRlc3ROYW1lPC9DX01FUkNIQU5UX05BTUU+PENfUE9TX05PPjAxOTgwMDA3PC9DX1BPU19OTz48Q19TRVJJQUxfTk8+MjAxNjAyMjk2NjY4PC9DX1NFUklBTF9OTz48VF9UUkFOU0FDVElPTl9EQVRFPjIwMTYwMjI5MTczMjU3PC9UX1RSQU5TQUNUSU9OX0RBVEU+PENfTUFDPjEyMzQ1Njc4OTBBQkNERUY8L0NfTUFDPjwvUk9PVD4K</originalData><mac>224A2C3C024D281D</mac></body></request>";
		String T_TRANSACTION_DATE=DateTime.timeToString(new Date());
		defaultRoot+="<C_NAME>0</C_NAME>";
		defaultRoot+="<C_TEL_NO>0</C_TEL_NO>";
		defaultRoot+="<T_TRANSACTION_DATE>"+T_TRANSACTION_DATE+"</T_TRANSACTION_DATE>";
		defaultRoot+="<C_MAC>"+DEFAULTC_MAC+"</C_MAC>";
		returnXml += defaultRoot;
		returnXml += "</ROOT>";
		String xorStr="";
		String resultMac="";
		try {
			xorStr=encode(returnXml.getBytes("gbk"));
			resultMac=XORUtil.getMac(xorStr);
		} catch (Exception e) {
			e.printStackTrace();
		}
		String rootXml = "<?xml version=\"1.0\" encoding=\"GBK\" ?>";
		rootXml+="<request>";
		rootXml+="<header>";
		rootXml+="<sender>ccb_pos</sender>";
		rootXml+="<time>"+T_TRANSACTION_DATE+"</time>";
		rootXml+="</header>";
		rootXml+="<body>";
		rootXml+="<originalData>";
		rootXml+=xorStr;
		rootXml+="</originalData>";
		rootXml+="<mac>"+resultMac+"</mac>";
		rootXml+="</body>";
		rootXml+="</request>";
		return rootXml;
	}
}
